

/**
 * @file CSSimulate.hpp
 * This class decimates GNSS Data Structures data given a csInterval interval,
 * a tolerance, and a starting epoch.
 */
#ifndef CSSimulate_HPP
#define CSSimulate_HPP


#include "Exception.hpp"
#include "ProcessingClass.hpp"
#include "CommonHeader.hpp"


namespace gpstk
{

      /// Thrown when some epoch data must be decimated
      /// @ingroup exceptiongroup
    NEW_EXCEPTION_CLASS(CSException, gpstk::Exception);


   class CSSimulate : public ProcessingClass
   {
   public:

         /// Default constructor
      CSSimulate()
         : 
           firstTime(true),
           csInterval(30.0), tolerance(0.5),
           CSGPSL1(0), CSGPSL2(0), CSGPSL5(0),
           CSGALL1(0), CSGALL5(0), CSGALL7(0), CSGALL8(0), CSGALL6(0),
           CSBDSL2(0), CSBDSL7(0), CSBDSL6(0),
           CSGPSAccumL1(0.0), CSGPSAccumL2(0.0), CSGPSAccumL5(0.0), 
           initialTime(CommonTime::BEGINNING_OF_TIME), 
           sumStream(NULL)
      {};


         /** Common constructor.
          *
          * @param interval      Sampling interval, in seconds.
          * @param tol                 Tolerance, in seconds.
          * @param initialEpoch        Epoch to start decimation.
          */
      CSSimulate( const double interval,
                  const double tol,
                  const CommonTime& initialEpoch )
         : csInterval(interval), tolerance(tol), initialTime(initialEpoch)
      {};


         /** Return a satTypeValueMap object, adding the new data generated
          *  when calling this object.
          *
          * @param time      Epoch corresponding to the data.
          * @param gData     Data object holding the data.
          */
      virtual satTypeValueMap& Process( const CommonTime& time,
                                        satTypeValueMap& gData )
         noexcept(false);


         /** Return a gnssRinex object, adding the new data generated
          *  when calling this object.
          *
          * @param gData    Data object holding the data.
          */
      virtual void Process(gnssRinex& gData)
         noexcept(false)
      { 
          Process(gData.header.epoch, gData.body); 
      };


         /** Return a sourceRinex object, adding the new data generated
          *  when calling this object.
          *
          * @param gData    Data object holding the data.
          */
      virtual void Process(commonHeader& comHeader,sourceRinex& gData)
         noexcept(false);


         /// Return csInterval interval, in seconds.
      virtual double getCSInterval(void) const
      { return csInterval; };

         /** Sets csInterval interval.
          *
          * @param interval      Sampling interval, in seconds.
          */
      virtual CSSimulate& setCSInterval(const double interval);

         /** Sets cycle slip size.
          */
      virtual CSSimulate& setSat(SatID& sat)
      {
         csSat = sat;
      };

         /** Sets cycle slip size.
          */
      virtual CSSimulate& setGPSCycleSlipL1(const double size)
      {
         CSGPSL1 = size;
      };

      virtual CSSimulate& setGPSCycleSlipL2(const double size)
      {
         CSGPSL2 = size;
      };

      virtual CSSimulate& setGPSCycleSlipL5(const double size)
      {
         CSGPSL5 = size;
      };

      virtual CSSimulate& setGALCycleSlipL1(const double size)
      {
         CSGALL1 = size;
      };

      virtual CSSimulate& setGALCycleSlipL5(const double size)
      {
         CSGALL5 = size;
      };

      virtual CSSimulate& setGALCycleSlipL7(const double size)
      {
         CSGALL7 = size;
      };

      virtual CSSimulate& setGALCycleSlipL8(const double size)
      {
         CSGALL8 = size;
      };

      virtual CSSimulate& setGALCycleSlipL6(const double size)
      {
         CSGALL6 = size;
      };

      virtual CSSimulate& setBDSCycleSlipL2(const double size)
      {
         CSBDSL2 = size;
      };

      virtual CSSimulate& setBDSCycleSlipL7(const double size)
      {
         CSBDSL7 = size;
      };

      virtual CSSimulate& setBDSCycleSlipL6(const double size)
      {
         CSBDSL6 = size;
      };

         /// Return tolerance, in seconds.
      virtual double getTolerance(void) const
      { return tolerance; };


         /** Sets tolerance, in seconds.
          * @param tol                 Tolerance, in seconds.
          */
      virtual CSSimulate& setTolerance(const double tol);

         /** Sets tolerance, in seconds.
          * @param tol                 Tolerance, in seconds.
          */
      virtual CSSimulate& setSumStream(std::ofstream& stream)
      {
          sumStream = &stream;
      };


         /** Sets epoch to start decimation.
          *
          * @param initialEpoch        Epoch to start decimation.
          */
      virtual CSSimulate& setInitialEpoch(const CommonTime& initialEpoch)
      { initialTime = initialEpoch; return (*this); };


         /// Return a string identifying this object.
      virtual std::string getClassName(void) const;


         /// Destructor
      virtual ~CSSimulate() {};


   private:

      bool firstTime;

         /// Sampling interval, in seconds
      double csInterval;

      double CSGPSL1;
      double CSGPSL2;
      double CSGPSL5;

      double CSGALL1;
      double CSGALL5;
      double CSGALL7;
      double CSGALL8;
      double CSGALL6;

      double CSBDSL2;
      double CSBDSL7;
      double CSBDSL6;

      std::ofstream* sumStream;

      SatID csSat;

      double CSGPSAccumL1;
      double CSGPSAccumL2;
      double CSGPSAccumL5;

      double CSGALAccumL1;
      double CSGALAccumL5;
      double CSGALAccumL7;
      double CSGALAccumL8;
      double CSGALAccumL6;

      double CSBDSAccumL2;
      double CSBDSAccumL7;
      double CSBDSAccumL6;

         /// Tolerance, in seconds
      double tolerance;

         /// Last processed epoch
      CommonTime initialTime;

   }; // End of class 'CSSimulate'

      //@}

}  // End of namespace gpstk

#endif   // CSSimulate_HPP
